<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>高级消息退场动画</title>
  <style>
    /* 保持之前的样式不变 */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Helvetica Neue', Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      background-color: #f5f5f5;
    }

    .container {
      width: 100%;
      max-width: 800px;
      padding: 20px;
    }

    .btn {
      padding: 10px 20px;
      background-color: #4a6bdf;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
      font-size: 16px;
      transition: background-color 0.3s;
      margin: 5px;
    }

    .btn:hover {
      background-color: #3a56c0;
    }

    .message-container {
      position: fixed;
      top: 20px;
      left: 0;
      right: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      pointer-events: none;
      z-index: 1000;
    }

    .message {
      padding: 12px 24px;
      margin-bottom: 10px;
      border-radius: 4px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      font-size: 14px;
      display: flex;
      align-items: center;
      max-width: 80%;
      opacity: 0;
      transform: translateY(-20px);
      will-change: transform, opacity;
    }

    .message.success {
      background-color: #f0f9eb;
      color: #67c23a;
      border: 1px solid #e1f3d8;
    }

    .message.error {
      background-color: #fef0f0;
      color: #f56c6c;
      border: 1px solid #fde2e2;
    }

    .message.warning {
      background-color: #fdf6ec;
      color: #e6a23c;
      border: 1px solid #faecd8;
    }

    .message.info {
      background-color: #edf2fc;
      color: #909399;
      border: 1px solid #ebeeff;
    }

    .message-icon {
      margin-right: 10px;
      font-size: 16px;
    }

    .controls {
      margin-top: 30px;
      background: white;
      padding: 20px;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    }

    .radio-group {
      margin: 15px 0;
    }

    label {
      margin-right: 15px;
      cursor: pointer;
    }
  </style>
</head>
<body>
<div class="container">
  <h1>消息退场动画演示</h1>
  <p>选择不同的退场动画效果并点击按钮测试</p>

  <div class="controls">
    <div class="radio-group">
      <label><input type="radio" name="animation" value="fade" checked> 淡出</label>
      <label><input type="radio" name="animation" value="slideUp"> 向上滑动</label>
      <label><input type="radio" name="animation" value="elastic"> 弹性消失</label>
      <label><input type="radio" name="animation" value="flip"> 3D翻转</label>
      <label><input type="radio" name="animation" value="particle"> 粒子消散</label>
    </div>

    <div>
      <button class="btn" id="successBtn">成功消息</button>
      <button class="btn" id="errorBtn">错误消息</button>
      <button class="btn" id="warningBtn">警告消息</button>
      <button class="btn" id="infoBtn">信息消息</button>
    </div>
  </div>
</div>

<div class="message-container" id="messageContainer"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js"></script>

<script>
  const messageTypes = {
    success: { icon: '✓' },
    error: { icon: '✗' },
    warning: { icon: '⚠' },
    info: { icon: 'ℹ' }
  };

  function getSelectedAnimation() {
    return document.querySelector('input[name="animation"]:checked').value;
  }

  function showMessage(type, text, duration = 3000) {
    const messageContainer = document.getElementById('messageContainer');
    const message = document.createElement('div');
    message.className = `message ${type}`;

    // 为粒子效果准备
    if(getSelectedAnimation() === 'particle') {
      const words = text.split(' ');
      text = '';
      words.forEach(word => {
        text += `<span style="display: inline-block">${word}&nbsp;</span>`;
      });
      message.innerHTML = `<span class="message-icon">${messageTypes[type].icon}</span>${text}`;
    } else {
      message.innerHTML = `<span class="message-icon">${messageTypes[type].icon}</span><span>${text}</span>`;
    }

    messageContainer.appendChild(message);

    const tl = gsap.timeline();

    // 入场动画
    tl.to(message, {
      duration: 0.4,
      opacity: 1,
      y: 0,
      ease: "back.out(1.7)"
    });

    // 停留时间
    tl.to(message, {
      duration: duration / 1000,
      opacity: 1
    });

    // 根据选择的动画类型应用不同的退场动画
    const animationType = getSelectedAnimation();
    applyExitAnimation(tl, message, animationType, type);
  }

  function applyExitAnimation(tl, element, animationType, messageType) {
    switch(animationType) {
      case 'slideUp':
        tl.to(element, {
          duration: 0.4,
          y: -40,
          opacity: 0,
          ease: "power1.in",
          onComplete: () => element.remove()
        });
        break;

      case 'elastic':
        tl.to(element, {
          duration: 0.5,
          opacity: 0,
          y: -30,
          scale: 0.8,
          ease: "elastic.in(1, 0.5)",
          onComplete: () => element.remove()
        });
        break;

      case 'flip':
        tl.to(element, {
          duration: 0.6,
          rotationX: 90,
          opacity: 0,
          transformOrigin: "50% 50%",
          ease: "back.in(1.2)",
          onComplete: () => element.remove()
        });
        break;

      case 'particle':
        const spans = element.querySelectorAll("span:not(.message-icon)");
        tl.to(spans, {
          duration: 0.6,
          opacity: 0,
          y: () => gsap.utils.random(-30, 30),
          x: () => gsap.utils.random(-30, 30),
          stagger: 0.02,
          ease: "power3.in",
          onComplete: () => element.remove()
        });
        break;

      case 'fade':
      default:
        tl.to(element, {
          duration: 0.3,
          opacity: 0,
          y: -20,
          ease: "power1.in",
          onComplete: () => element.remove()
        });
    }

    // 为错误消息添加特殊震动效果
    if(messageType === 'error' && animationType !== 'particle') {
      tl.to(element, {
        duration: 0.1,
        x: 5,
        repeat: 3,
        yoyo: true,
        ease: "sine.inOut"
      }, "-=0.2");
    }
  }

  // 绑定按钮事件
  document.getElementById('successBtn').addEventListener('click', () => {
    showMessage('success', '操作成功完成！这是一条成功消息。');
  });

  document.getElementById('errorBtn').addEventListener('click', () => {
    showMessage('error', '操作失败！发生了未知错误。');
  });

  document.getElementById('warningBtn').addEventListener('click', () => {
    showMessage('warning', '警告！您正在执行敏感操作。');
  });

  document.getElementById('infoBtn').addEventListener('click', () => {
    showMessage('info', '提示：这是信息类消息，仅供参考。');
  });
</script>
</body>
</html>